package net.cloudsun.graph.puzzle.relation;

import net.cloudsun.graph.puzzle.*;

import java.util.function.Function;

/**
 * 逆时针旋转
 * 根据群的位置和元素本身的位置，那么就有4*4种情况
 * 1 本身位置在四角,这个时候，群的位置也确定了
 * 2 本身在边的中点，这个时候同时属于两个群，有两种计算
 * 3 本身在最中央，这个时候同时属于4个群，有四种计算
 * 或者从另一个维度计算
 * <p>
 * created at 25/11/2021
 *
 * @author 俞建波
 * <a href="mailto://yujianbo@chtwm.com">yujianbo@chtwm.com</a>
 * @since 1.2.0
 */
public enum SmallAnticlockwiseRotate implements Function<JigsawState, JigsawState> {
    /**
     * 1 如果属于top left,那么当
     * 1.1 row == column, right (1,1)or left(0,0)
     * 1.2 row < column, down
     * 1.3 row > column, up
     * 其实就是活动点在整个子群的位置。
     */
    TOP_LEFT(location -> {
        final Integer row = location.getA();
        final Integer column = location.getB();
        return positionInSubGroup(row, column);
    }),

    TOP_RIGHT(location -> {
        // 0 1 0 2 1 1 1 2
        // 这个时候 column -1 就可以了
        final Integer row = location.getA();
        final Integer column = location.getB() -1;
        return positionInSubGroup(row, column);
    }), BOTTOM_LEFT(location -> {
        final Integer row = location.getA() -1;
        final Integer column = location.getB();
        return positionInSubGroup(row, column);
    }), BOTTOM_RIGHT(location -> {
        final Integer row = location.getA()-1;
        final Integer column = location.getB()-1;
        return positionInSubGroup(row, column);
    });

    private static PuzzleDirection getMoveDirection(PuzzlePosition position) {

            switch (position) {
                case TOP_RIGHT:
                    return PuzzleDirection.LEFT;
                case TOP_LEFT:
                    return PuzzleDirection.DOWN;
                case BOTTOM_LEFT:
                    return PuzzleDirection.RIGHT;
                case BOTTOM_RIGHT:
                    return PuzzleDirection.UP;
            }
            return null;
    }

    private static PuzzlePosition positionInSubGroup(Integer row, Integer column) {
        if (row < column) {
            return PuzzlePosition.TOP_RIGHT;
        }
        if (row > column) {
            return PuzzlePosition.BOTTOM_LEFT;
        }
        if (row == 0) {
            return PuzzlePosition.TOP_LEFT;
        }
        return PuzzlePosition.BOTTOM_RIGHT;
    }

    private final Function<Pair<Integer>, PuzzlePosition> positionFunction;

    SmallAnticlockwiseRotate(Function<Pair<Integer>, PuzzlePosition> positionFunction) {
        this.positionFunction = positionFunction;
    }

    public static SmallAnticlockwiseRotate ofPosition(PuzzlePosition code) {

        switch (code) {
            case TOP_LEFT:
                return TOP_LEFT;
            case TOP_RIGHT:
                return TOP_RIGHT;
            case BOTTOM_LEFT:
                return BOTTOM_LEFT;
            case BOTTOM_RIGHT:
                return BOTTOM_RIGHT;
            default:
                return null;
        }
    }

    /**
     * 总共8个位置
     * 每个位置只有一个方向。这就是顺时针旋转
     * 右 右 下
     * 上 空 下
     * 上 左 左
     * 逆运算
     * 下 左 左
     * 下 空 上
     * 右 右 上
     *
     * @param start
     * @return
     */
    @Override
    public JigsawState apply(JigsawState start) {
        final Pair<Integer> location = PuzzleStateRelation.getLocation(start, 8);
        final PuzzlePosition position = this.positionFunction.apply(location);
        final int[][] ints = start.toArray();
        PuzzleDirection direction = getMoveDirection(position);
        PuzzleStateRelation.swap(ints, location, direction);
        return new JigsawState(ints);
    }
}
